import {commonTreeNode} from '../../type';

export const demo =():void=>{
    console.log("jakotsu!!");
};

// 按条件查询子节点
export const treeFind=(tree:Array<commonTreeNode>,func:Function|undefined):any=>{
    if(tree&&tree.length>0){
        for (const data of tree) {
            if (typeof func == 'function'){
                if (func(data)) return data;
            }else{
                return data;
            }
            if(!data.children){
                data.children = [];
            }
            const res = treeFind(data.children, func);
            if (res) return res
        };
    }
    return [];
};

// 深克隆
export function deepClone<T extends {hasOwnProperty:any}>(obj:T):T{
    if(!obj) return obj;
    const result = (Array.isArray(obj)?[]:{}) as any;
    for(const key in obj){
        if(obj.hasOwnProperty(key)){
            if(typeof obj[key] === 'object' && obj[key] !== null){
                result[key] = deepClone(obj[key]);
            }else{
                result[key] = obj[key];
            }
        }
    }
    return result;
}

// 手写compose函数
export const compose =(...fn):any=>{
    if(!fn.length) return (v:unknown)=>v;
    if(fn.length == 1) return fn[0];
    return fn.reduce((pre,cur)=>(...args)=>pre(cur(args)));
};

// 手写函数的柯里化
export const curry =(fn):any=>{
    if(!fn) return undefined;
    return function curried(...args){
        if(args.length>=fn.length){
            fn.apply(this,...args);
        }else{
            return function(...args2){
                return curried.apply(this,args.concat(args2));
            }
        }
    }
};

// 手写防抖
export const debounce =(fn:(...args:unknown[])=>unknown,timeout = 600)=>{
    let timer:ReturnType<typeof setTimeout>;
    return function(this:Window,...args:unknown[]){
        clearTimeout(timer);
        timer = setTimeout(()=>{
            fn.apply(this,args);
        },timeout);
    }
};


// 获取对象数组的指定字段的值集合
export const getArrayValueByParam =(arr:any[],param:string,limits?:any[]):any[]=>{
    if(param&&arr&&arr.length>0){
        if(limits&&limits.length>0){
            return arr.map((x:any)=>{
                if(limits.includes(x[param])){
                    return x[param];
                }
            })
        }else{
            return arr.map((x:any)=>x[param]);
        }
    }else{
        return []
    }
}

export const getArrayItemWithParamLimit =(arr:any[],param:string,limits?:any[]):any[]=>{
    if(param&&arr&&arr.length>0){
        if(limits&&limits.length>0){
            return arr.filter((x:any)=>{
                if(limits.includes(x[param])){
                    return x;
                }
            })
        }else{
            console.warn("If no filter condition is added, the full array will be returned");
            return arr;
        }
    }else{
        console.warn("If no filter condition is added, the full array will be returned");
        return arr;
    }
}

// 清空参数数组返回符合条件的新数组
export const transferArray=(arr:any[],fn:Function):any[]=>{
    let result = [];
    for(;arr.length>0;){
        let sitem = arr.shift();
        if(fn){
            let item = fn(sitem);
            if(item){
                result.push(fn(item));
            }
        }else{
            result.push(sitem);
        }
    }
    return result;
};

// 数组去重
export const simpleDeDupArray =(arr:any[]):any[]=>{
    return Array.from(new Set(arr));
};

// js基本类型取不同
export const getArrDifference =(arr1:any[], arr2:any[]):any[]=> {
    return arr1.concat(arr2).filter(function(v, i, arr) {
        return arr.indexOf(v) === arr.lastIndexOf(v);
    });
}
// js基本类型取相同
export const getArrEqual =(arr1:any[], arr2:any[]):any[]=> {
    let newArr = [];
    for (let i = 0; i < arr2.length; i++) {
        for (let j = 0; j < arr1.length; j++) {
            if(arr1[j] === arr2[i]){
                newArr.push(arr1[j]);
            }
        }
    }
    return newArr;
}

// 按指定字段取出两个对象数组的相同部分
export const getArrayCoin=(a:any[],b:any[],str:string):any[]=>{
    if(str&&a&&a.length>0&&b&&b.length>0){
        let aps:any[] = getArrayValueByParam(a,str);
        let bps:any[] = getArrayValueByParam(b,str);
        let diff:any[] = getArrEqual(aps,bps);
        if(diff&&diff.length>0){
            let result = getArrayItemWithParamLimit(a,"id",diff);
            return result;    
        }else{
            return [...aps];
        }
    }else{
        console.warn("Function only supports two arrays with length greater than 0");
    }
    return [];
};

// 按指定字段取出两个对象数组的不同部分
export const getArrayDiff=(a:any[],b:any[],str:string):any[]=>{
    if(str&&a&&a.length>0&&b&&b.length>0){
        let aps:any[] = getArrayValueByParam(a,str);
        let bps:any[] = getArrayValueByParam(b,str);
        let diff:any[] = getArrDifference(aps,bps);
        if(diff&&diff.length>0){
            let result1 = getArrayItemWithParamLimit(a,"id",diff);
            let result2 = getArrayItemWithParamLimit(b,"id",diff);
            return result1.concat(result2);    
        }else{
            return [...aps];
        }
    }else{
        console.warn("Function only supports two arrays with length greater than 0");
    }
    return [];
};

export const listToTree=(list:any[],cstr:string,pstr:string):any[]=>{
    let cid = 'id';
    let pid = 'parentId';
    if(cstr){ cid = cstr };
    if(pstr){ pid = pstr };
    const info = list.reduce((map,node)=>(map[node[cid]] = node,node.children = [],map),{});
    return list.filter(node=>{
        node[pid] && info[node[pid]].children.push(node);
        return !node[pid];
    })
};

export const getCurrentScript =():any=>{
    let DOC = document;
    //获取正在解析的script节点
    if(DOC.currentScript){ // firefox 4+
        let cscript:any = DOC.currentScript; 
        return cscript.src;
    }
    let stack;
    let a:any;
    let e:string;
    let i:string;
    let node;
    try{
        a.b.c();
    }catch(e){
        stack = e.stack;
    }
    if(stack){
        e = stack.indexOf('at')!==-1?'at':'@';
        i = stack.lastIndexOf(e);
        let a = stack.slice(i+e.length).replace(/\s\s*$/,"").replace(/(:\d+)?:\d+$/i,"");
        return a;
    }
    let nodes = DOC.head.getElementsByTagName("script");
    for(let i =0;node = nodes[i++];){
        if(node.readyState === 'interactive'){
            return node.className = node.src;
        }
    }
}